package com.hyg.base.ui.activity;

import android.annotation.SuppressLint;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.net.http.SslError;
import android.os.Build;
import android.os.Bundle;
import android.os.Process;
import android.text.TextUtils;
import android.util.Log;
import android.view.KeyEvent;
import android.view.View;
import android.webkit.CookieManager;
import android.webkit.CookieSyncManager;
import android.webkit.SslErrorHandler;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.FrameLayout;
import android.widget.TextView;

import com.hyg.base.R;
import com.hyg.base.listener.JSObject;
import com.hyg.base.ui.base.BaseActivity;
import com.hyg.base.ui.base.BasePresenter;
import com.hyg.common.utils.FileUtils;
import com.hyg.common.utils.LogUtils;

import java.io.File;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

public class WebViewActivity extends BaseActivity {
    private static final String TAG = "WebView";

    private FrameLayout layoutWebView;
    protected WebView webView;
    private TextView tvTitle;
    protected String webUrl;

    @Deprecated
    public static void launch(Context from,String webUrl){
        if(TextUtils.isEmpty(webUrl)) return;
        Intent intent = new Intent(from, WebViewActivity.class);
        intent.putExtra("webUrl",webUrl);
        from.startActivity(intent);
    }

    @Override
    protected int provideContentViewId() {
        return R.layout.lib_activity_webview;
    }

    @Override
    protected void init(Bundle savedInstanceState) {
        findViewById(R.id.lay_title_bar).setVisibility(showTitleBar()?View.VISIBLE:View.GONE);
        webUrl = getIntent().getStringExtra("webUrl");
        layoutWebView = findViewById(R.id.layoutWebView);
        tvTitle = findViewById(R.id.tv_title);
        webView = new WebView(getApplicationContext());
        WebSettings settings = webView.getSettings();
        settings.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.NARROW_COLUMNS);
        webView.setScrollBarStyle(View.SCROLLBARS_INSIDE_OVERLAY);
        layoutWebView.addView(webView);
        initWebview();

        if(!TextUtils.isEmpty(webUrl)){
            webView.loadUrl(webUrl);
        }
        webView.addJavascriptInterface(new JSObject(),"ytlive");
    }

    @Override
    protected BasePresenter createPresenter() {
        return null;
    }

    protected void loadUrl(String url) {
        webUrl = url;
        webView.loadUrl(url);
    }

    protected boolean showTitleBar(){
        return true;
    }

    @SuppressLint("NewApi")
    protected void initWebview(){
        webView.requestFocusFromTouch();// 支持获取手势焦点，输入用户名、密码或其他
        webView.getSettings().setBlockNetworkImage(false);//解决图片不显示
        webView.getSettings().setJavaScriptEnabled(true);//启用js
        webView.getSettings().setDomStorageEnabled(true);//防止web的js写法不规范加载不出页面
        webView.getSettings().setJavaScriptCanOpenWindowsAutomatically(true);
        webView.getSettings().setDefaultTextEncodingName("utf-8");
        webView.getSettings().setMediaPlaybackRequiresUserGesture(false);
        webView.setWebViewClient(new WebViewClient() {
            public boolean shouldOverrideUrlLoading(WebView view, String url) {
                WebView.HitTestResult hit = view.getHitTestResult();
                //hit.getExtra()为null或者hit.getType() == 0都表示即将加载的URL会发生重定向，需要做拦截处理
                if (TextUtils.isEmpty(hit.getExtra()) || hit.getType() == 0) {
                    //通过判断开头协议就可解决大部分重定向问题了，有另外的需求可以在此判断下操作
                    LogUtils.e("重定向", "重定向: " + hit.getType() + " && EXTRA（）" + hit.getExtra() + "------");
                    LogUtils.e("重定向", "GetURL: " + view.getUrl() + "\n" +"getOriginalUrl()"+ view.getOriginalUrl());
                    LogUtils.d("重定向", "URL: " + url);
                }

                if (url.startsWith("http://") || url.startsWith("https://")) { //加载的url是http/https协议地址
                    view.loadUrl(url);
                    return false; //返回false表示此url默认由系统处理,url未加载完成，会继续往下走
                } else { //加载的url是自定义协议地址
                    try {
                        Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
                        WebViewActivity.this.startActivity(intent);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                    return true;
                }
            }
            public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
                handler.proceed();
            }
            @Override
            public void onPageFinished(WebView view, String url) {
                super.onPageFinished(view, url);
                tvTitle.setText(view.getTitle());
//                view.loadUrl("javascript:document.getElementById('logo').onclick = function(){window.ytlive.onCallback(8,{\"success\":false,\"message\":\"无效的Token\",\"code\":\"UOUE0005\",\"dicts\":{}})}");
//                view.loadUrl("javascript:document.getElementById('logo').onclick = function(){javascript:ytlive.onCallback(8,{\"success\":false,\"message\":\"无效的Token\",\"code\":\"UOUE0005\",\"dicts\":{}})}");
            }

        });
    }

    @Override
    protected void onDestroy() {
        clearWebViewCache();
        super.onDestroy();
    }

    @SuppressLint("NewApi")
    public void clearWebViewCache(){
        if (this.webView != null) {
            layoutWebView.removeAllViews();
            webView.loadDataWithBaseURL(null, "", "text/html", "utf-8", null);
            webView.clearCache(true);
            webView.clearHistory();
            webView.clearFormData();
            webView.removeAllViews();
            webView.destroy();
        }

        CookieSyncManager.createInstance(this);
        CookieManager cookieManager = CookieManager.getInstance();
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            cookieManager.removeSessionCookies(null);
            cookieManager.removeAllCookie();
            cookieManager.flush();
        } else {
            cookieManager.removeSessionCookies(null);
            cookieManager.removeAllCookie();
            CookieSyncManager.getInstance().sync();
        }

        //清理Webview缓存数据库
        try {
            deleteDatabase("webview.db");
            deleteDatabase("webviewCache.db");
        } catch (Exception e) {
            e.printStackTrace();
        }

        File webviewCacheDir = new File(getCacheDir().getAbsolutePath()+"/webviewCache");
        FileUtils.deleteFile(webviewCacheDir);

        File file = this.getApplicationContext().getCacheDir().getAbsoluteFile();
        FileUtils.deleteFile(file);
    }

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        //如果按下的是回退键且历史记录里确实还有页面
        if ((keyCode == KeyEvent.KEYCODE_BACK) && webView.canGoBack()) {
            webView.goBack();
            return true;
        }
        return super.onKeyDown(keyCode, event);
    }

    @Override
    public void finish() {
        super.finish();
    }

    /**
     * 由于webView存在安全漏洞,谷歌从5.1开始全面禁止系统应用使用webview,使用会导致应用崩溃错误提示:
     * Caused by: java.lang.UnsupportedOperationException: For security reasons, WebView is not allowed in privileged processes.
     * 解决方法，在创建 WebView 之前运行此方法。
     */
    public static void hookWebView() {
        // 如果是非系统进程则按正常程序走
        if (Process.myUid() != Process.SYSTEM_UID) {
            return;
        }
        int sdkInt = Build.VERSION.SDK_INT;
        try {
            Class<?> factoryClass = Class.forName("android.webkit.WebViewFactory");
            Field field = factoryClass.getDeclaredField("sProviderInstance");
            field.setAccessible(true);
            Object sProviderInstance = field.get(null);
            if (sProviderInstance != null) {
                Log.i(TAG, "sProviderInstance isn't null");
                return;
            }

            Method getProviderClassMethod;
            if (sdkInt > 22) {
                getProviderClassMethod = factoryClass.getDeclaredMethod("getProviderClass");
            } else if (sdkInt == 22) {
                getProviderClassMethod = factoryClass.getDeclaredMethod("getFactoryClass");
            } else {
                Log.i(TAG, "Don't need to Hook WebView");
                return;
            }
            getProviderClassMethod.setAccessible(true);
            Class<?> factoryProviderClass = (Class<?>) getProviderClassMethod.invoke(factoryClass);
            Class<?> delegateClass = Class.forName("android.webkit.WebViewDelegate");
            Constructor<?> delegateConstructor = delegateClass.getDeclaredConstructor();
            delegateConstructor.setAccessible(true);
            if (sdkInt < 26) {//低于Android O版本
                Constructor<?> providerConstructor = factoryProviderClass.getConstructor(delegateClass);
                if (providerConstructor != null) {
                    providerConstructor.setAccessible(true);
                    sProviderInstance = providerConstructor.newInstance(delegateConstructor.newInstance());
                }
            } else {
                Field chromiumMethodName = factoryClass.getDeclaredField("CHROMIUM_WEBVIEW_FACTORY_METHOD");
                chromiumMethodName.setAccessible(true);
                String chromiumMethodNameStr = (String) chromiumMethodName.get(null);
                if (chromiumMethodNameStr == null) {
                    chromiumMethodNameStr = "create";
                }
                Method staticFactory = factoryProviderClass.getMethod(chromiumMethodNameStr, delegateClass);
                if (staticFactory != null) {
                    sProviderInstance = staticFactory.invoke(null, delegateConstructor.newInstance());
                }
            }

            if (sProviderInstance != null) {
                field.set("sProviderInstance", sProviderInstance);
                Log.i(TAG, "Hook success!");
            } else {
                Log.i(TAG, "Hook failed!");
            }
        } catch (Throwable e) {
            Log.w(TAG, e);
        }
    }
}
